/**
 * 向后台异步跨域请求json数据
 * Fetch 是浏览器提供的原生 AJAX 接口，对其进行封装。
 * doc: https://github.com/github/fetch
*/

import {
    baseUrl
} from './env'
/**
 * 请求后端数据
 * 默认type = 'GET', method = 'fetch'
*/
export default async (url = '', data = {}, type = 'GET', method = 'fetch') => {
    // 转大写
    type = type.toUpperCase();
    // 完整的请求路径
    url = baseUrl + url;

    /**
     * GET方式
     * 拼接请求路径+请求参数
    */
    if (type == 'GET') {
        let dataStr = ''; //数据拼接字符串
        /**
         * 该方法把对象拼接成"key=value&"字符串
         * Object.keys(obj)
         *   参数：{key:value}对象
         *   返回值：对象key数组
         * forEach(key)
         *   参数：数组下标
        */
        Object.keys(data).forEach(key => {
            dataStr += key + '=' + data[key] + '&';
        })
        /**
         * 如果存在请求，把拼接的字符串在第一个key前添加“?”
        */
        if (dataStr !== '') {
            dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
            url = url + '?' + dataStr;
        }
    }

    // 使用fetch请求
    if (window.fetch && method == 'fetch') {
        // 请求头参数
        let requestConfig = {
            credentials: 'include', //为了在当前域名内自动发送 cookie ， 必须提供这个选项
            method: type,
            headers: {
                'Accept': 'application/json',
                'Content-Type': 'application/json'
            },
            mode: "cors",//跨域请求的模式
            cache: "force-cache"
        }

        // POST方式，将data对象转为json字符串，并在requestConfig对象的body属性中添加
        if (type == 'POST') {
            // Object.defineProperty() 方法会直接在一个对象上定义一个新属性，或者修改一个对象的现有属性，并返回此对象。
            Object.defineProperty(requestConfig, 'body', {
                value: JSON.stringify(data)
            })
        }

        // fetch请求
        try {
            const response = await fetch(url, requestConfig);
            const responseJson = await response.json();
            return responseJson
        } catch (error) {
            throw new Error(error)
        }
    } else {//使用AJAX原始对象XMLHttpRequest请求
        return new Promise((resolve, reject) => {
            let requestObj;
            if (window.XMLHttpRequest) {
                requestObj = new XMLHttpRequest();
            } else {
                requestObj = new ActiveXObject;
            }

            let sendData = '';
            if (type == 'POST') {
                sendData = JSON.stringify(data);
            }

            requestObj.open(type, url, true);
            requestObj.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            requestObj.send(sendData);

            requestObj.onreadystatechange = () => {
                if (requestObj.readyState == 4) {
                    if (requestObj.status == 200) {
                        let obj = requestObj.response
                        if (typeof obj !== 'object') {
                            obj = JSON.parse(obj);
                        }
                        resolve(obj)
                    } else {
                        reject(requestObj)
                    }
                }
            }
        })
    }
}
